package com.mzlalal.donate.controller;

import com.mzlalal.donate.model.Donate;
import com.mzlalal.donate.model.QRCode.QRCode;
import com.mzlalal.donate.model.comm.Results;
import com.mzlalal.donate.model.enums.ScanStatusEnum;
import com.mzlalal.donate.service.DonateService;
import com.mzlalal.donate.utils.QrCodeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.util.UUID;

/**
 * @description: 二维码生成
 * @author: Mzlalal
 * @date: 2019/12/26 16:54
 * @version: 1.0
 */
@Slf4j
@Validated
@RestController
@RequestMapping("/QRCode")
public class DonateController {

    @Autowired
    RedisTemplate redisTemplate;

    @Value("${qrCode.callback.url}")
    private String callbackUrl;

    @Autowired
    DonateService donateService;

    /**
     * 生成捐款图片二维码
     *
     * @param donate 姓名 金额
     * @return
     */
    @RequestMapping("/scan/generateDonate")
    public QRCode generateDonateQRCode(@Valid Donate donate) {
        // 生成请求ID
        String token = UUID.randomUUID().toString();

        // 设置成为未扫描状态
        donate.setScanStatusEnum(ScanStatusEnum.SCAN_NO);

        // 缓存起来
        redisTemplate.opsForValue().set(token, donate);

        return QRCode.builder()
                .baseImage(QrCodeUtil.toBase64(callbackUrl + "?token=" + token, 300, 300))
                .token(token)
                .build();
    }

    /**
     * 扫码成功
     *
     * @param token 请求ID
     * @return
     */
    @RequestMapping("/scan/ok")
    public Results ok(@NotBlank String token) {
        // 获取唯一请求ID
        if (redisTemplate.hasKey(token)) {
            // 获取请求唯一ID的 Donate
            Object temp = redisTemplate.opsForValue().get(token);
            Assert.isInstanceOf(Donate.class, temp, "当前请求已经过期! 请重新生成二维码!");
            Donate donate = (Donate) temp;
            // 判断状态
            if (donate.getScanStatusEnum().name().equals(ScanStatusEnum.SCAN_NO.name())) {
                return donateService.insertDonateRecord(token, donate);
            } else {
                return this.validateScanStatus(donate.getScanStatusEnum());
            }
        }
        return Results.FAIL("-1", "当前请求已经过期! 请重新生成二维码!");
    }

    /**
     * 查看请求是否被处理完毕
     *
     * @param token 请求ID
     * @return
     */
    @RequestMapping("/scan/loop")
    public Results loop(@NotBlank String token) {
        // 获取唯一请求ID
        System.out.println(token);
        if (redisTemplate.hasKey(token)) {
            Object temp = redisTemplate.opsForValue().get(token);
            Assert.isInstanceOf(Donate.class, temp, "当前请求已经过期!");
            Donate donate = (Donate) temp;
            // 判断状态 是否为请求成功
            if (donate.getScanStatusEnum().name().equals(ScanStatusEnum.SCAN_YES.name())) {
                String msg = new StringBuilder()
                        .append("感谢 ")
                        .append(donate.getName())
                        .append(" 您捐献的 ")
                        .append(donate.getMoneyAmount())
                        .append(" 元!").toString();
                // 删除请求ID
                redisTemplate.delete(token);
                return Results.OK("0", msg);
            } else {
                return this.validateScanStatus(donate.getScanStatusEnum());
            }
        }
        return Results.FAIL("-1", "当前请求异常!请重新进行请求!");
    }

    /**
     * 验证二维码扫描状态
     *
     * @param scanStatusEnum
     * @return
     */
    private Results validateScanStatus(ScanStatusEnum scanStatusEnum) {
        switch (scanStatusEnum) {
            case SCAN_YES:
                return Results.FAIL("已扫描当前二维码!正在请求处理中...请稍后...");
            case SCAN_OK:
                return Results.FAIL("请求已经成功处理!");
            case SCAN_FAIL:
                return Results.FAIL("请求处理失败!请重新生成二维码进行扫描!");
            case SCAN_NO:
                return Results.FAIL("未扫描当前二维码!");
            default:
                return Results.FAIL("出现了未知的错误!");
        }
    }
}
